home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / HDX_BACK / HDX401 / SECT.C < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-09  |  20.5 KB  |  845 lines

  1. /* sect.c */
  2.  
  3. /* 
  4.  * Aug-23-88 jye. Change and add codes so that can be used for MS-DOS
  5.  * Dec-20-89 jye. Free a bug that HDX gives a error message when CD-ROM 
  6.  *                  is busy. 
  7.  */
  8.  
  9. #include "obdefs.h"
  10. #include "osbind.h"
  11. #include "mydefs.h"
  12. #include "part.h"
  13. #include "hdx.h"
  14. #include "addr.h"
  15. #include "error.h"
  16.  
  17. #define    ZBUFSIZ    0x4000        /* about 16k == 32 sectors */
  18. #define    ZCOUNT    (ZBUFSIZ/0x200)    /* ZCOUNT = 32 */
  19. #define MAXUNITS 16            /* max number of logical units */
  20.  
  21. #define PUNINFO struct _punifno
  22. PUNINFO {
  23.         WORD puns;    /* number of physical units */
  24.         BYTE pun[MAXUNITS];
  25.         LONG partition_start[MAXUNITS]; /* offset to partition on */
  26.                                         /* physical unit */
  27. };
  28. extern long ostack;        /* old stack pointer */
  29. extern UWORD errcode();        /* function to return error code */
  30. extern int yesscan;        /* the flag for the func. IBMGPART use */
  31. extern long sptrk;        /* the sector per track */
  32. extern int npart;        /* the number of partitions */
  33. extern int ext;            /* the index of extended partition */
  34. extern int extend;        /* the index of end extended partition */
  35. extern int showmany;    /* the flag for show the too many device alert box */
  36. extern char ttscsi;        /* the flag for SCSI if set */
  37. extern int needscan;    /* TRUE: if it is the first time to scan the units */
  38. extern int athead;        /* the # of data heads on the AT drive */
  39. extern int atcyl;        /* the # of cylinders on the AT drive */
  40. extern int atspt;        /* the # of sectors per track on the AT drive */
  41. extern int noacsi;        /* set for no ACSI drive in the system */
  42. /*
  43.  * Logical-to-dev+partition mapping table.
  44.  */
  45. int nlogdevs;                /* # logical devices */
  46. LOGMAP logmap[EXTRALOGD];    /* logical dev map */
  47. int livedevs[MAXPHYSDEVS];    /* live devs flags; 1: device is alive */
  48. int typedev = 0x0000;        /* if set, driver is a removable driver */
  49. int typedrv = 0x0000;        /* if set, driver is a SCSI driver */
  50. int atexst;                    /* AT drive exists */
  51. int slvexst;                /* AT slave drive exists */
  52. char useblit;                /* set for it is not the stbook drive */
  53.  
  54.  
  55. /*
  56.  * Rebuild logical-to-physical mapping
  57.  * by reading and interpreting the root
  58.  * blocks for all physical devs.
  59.  *
  60.  */
  61.  
  62. rescan(flag, znm)
  63.  
  64. int flag;    /* 0: don't report medium change error; */
  65.             /* non-0: report medium change error; */
  66. int znm;    /* 1: do zero & markbad; 0: do partition & format */
  67.  
  68. {
  69.     int dev, scan=0;
  70.     char buf[512];
  71.     char sendata[16];
  72.     int partno, ret, inqret, i;
  73.     PART *partinfo;
  74.     char mask = 0x80;    /* 7th bit is set on */
  75.     int setmask;
  76.     int maxloop;
  77.  
  78.     noacsi = 1;                /* assume there is no ACSI in the system */
  79.     ostack = Super(NULL);    /* set supervice mode */
  80.     ttscsi = chkscsi();        /* check if SCSI exists */
  81.     delay();
  82.     if ((atexst = chkide()))    { /* AT drive exist */
  83.         useblit = (stbook())?(0):(1);
  84.         if ((ret = identify(16, buf)) == OK)    {
  85.             delay();
  86.             /* return the number of cylinder, head, spt */
  87.             gparmfc(&atcyl, &athead, &atspt, buf);
  88.         } else { 
  89.             delay();
  90.             Super(ostack);
  91.             ret = errcode(16);
  92.             if (tsterr(ret) != OK) 
  93.                 return ERROR;
  94.             return (-3);    /* don't have to show the alert box */
  95.         }
  96.     }
  97.     delay();
  98.     /*
  99.     if ((atexst) && (slvexst = slave()))    {  AT slave drive exist 
  100.         if ((ret = identify(17, buf)) == OK)    {
  101.             atscyl = getword(buf+2);
  102.             atshead = getword(buf+6);
  103.             atsspt = getword(buf+12);
  104.             delay();
  105.         } else { 
  106.             delay();
  107.             Super(ostack);
  108.             ret = errcode(17);
  109.             if (tsterr(ret) != OK) 
  110.                 return ERROR;
  111.             return (-3);    don't have to show the alert box
  112.         }
  113.     }
  114.     */
  115.     delay();
  116.     Super(ostack);
  117.     /* set the scent message box */
  118.     if ((needscan) && (ttscsi))
  119.         dsplymsg(scanmsg);
  120.  
  121.     /* disable all logical and physical devs */
  122.     for (dev = 0; dev < EXTRALOGD; ++dev)
  123.         logmap[dev].lm_physdev = -1;
  124.  
  125.     for (dev = 0; dev < MAXPHYSDEVS; ++dev)
  126.         livedevs[dev] = 0;
  127.  
  128.     /*
  129.      * Scan all physical devs
  130.      * and pick up partition structures.
  131.      */
  132.     nlogdevs = 0;
  133.     showmany = 0;
  134.     if (atexst)    {
  135.         maxloop = 18;
  136.         dev = 16;
  137.     } else if (ttscsi)    {
  138.         maxloop = 16;
  139.         dev = 8;
  140.     } else {
  141.         maxloop = 8;
  142.         dev = 0;
  143.     }
  144. rerescan:
  145.     for (; dev < maxloop; ++dev)
  146.     {
  147.  
  148.         if (((dev == 16) && atexst) || ((dev == 17) && slvexst))    {
  149.             if ((ret = getroot(dev, buf, (SECTOR)0)) != 0)    {
  150.                 if (tsterr(ret) != OK)    
  151.                     err(rootread);
  152.                 return(ERROR);
  153.             }
  154.             goto atst;    /* skip and do the at stuff only */
  155.         }
  156.         /* initialize the buffer */
  157.         for (i = 0; i < 16; i++)        {
  158.             sendata[i] = 0;
  159.         }
  160.  
  161.         /* check see the drive is a what kind of drive */
  162.            ostack = Super(NULL);
  163.            delay();
  164.         inqret = inquiry(dev, (WORD)16, sendata);
  165.            delay();
  166.            Super(ostack);
  167.         setmask = 0x0001;
  168.         if (inqret & 0x08)    { /* the device is busy */
  169.             continue;
  170.         }
  171.         /* ret not equal OK, it may be a regular hard drive */
  172.         if (inqret == OK)         {     /* it is not a regular hard drive */
  173.             if (sendata[0])      {    /* it is not a hard drive */
  174.                 continue;
  175.             } else if (sendata[1] & mask)    { /* it is a removable drive */
  176.                 ;            /* don't set the SCSI bit */
  177.             } else {
  178.                   /* it is a SCSI drive */
  179.                 /* set the relative bit, 1 is a SCSI, other is not */
  180.                 typedrv |= setmask << dev;
  181.             }
  182.         }
  183.         if ((ret = getroot(dev, buf, (SECTOR)0)) < 0) {
  184.             if (znm)  rangelog(dev);
  185.             continue;
  186.         } else {        /* ret >= 0 */
  187.             if (ret > 0) {
  188.                 if ((flag) && (tsterr(ret) == OK))    {    
  189.                 /* if non-0, report error if medium changed */
  190.                         erasemsg();
  191.                          return ERROR;
  192.                 }
  193.                 if ((ret = getroot(dev, buf, (SECTOR)0))) {    /* try again */
  194.                     if (ret > 0 && flag && tsterr(ret) == OK)    {
  195.                         erasemsg();
  196.                         return ERROR;
  197.                     } else if ((ret > 0) && (!flag))    {
  198.                         if ((inqret == OK) && (sendata[1] & mask))    { 
  199.                             /* it is a removable drive */
  200.                             /* but forget insert the cartridge */
  201.                             err(instdrv);
  202.                             erasemsg();
  203.                         }
  204.                     }
  205.                     if (znm)    {
  206.                         rangelog(dev);
  207.                     }
  208.                     continue;
  209.                 }
  210.             }
  211.             if (inqret == OK)     {  /* it is a SCSI drive */
  212.                 if (sendata[1] & mask)    { /* it is a removable drive */
  213.                     /* set the relative bit, 1 is a removable, other is not */
  214.                     typedev |= setmask << dev;
  215.                 }
  216.             }
  217.     atst:
  218.             if (dev < 7)    /* there is a ACSI drive in the system */
  219.                 noacsi = 0;
  220.             livedevs[dev] = 1;
  221.             yesscan = 1;
  222.             if (stgpart(dev, buf, (PART *)&partinfo) == ERROR)    {
  223.                 erasemsg();
  224.                 return ERROR;
  225.             }
  226.             if (ext != NO_EXT)    {
  227.                 sortpart(partinfo,SCAN_BS); 
  228.             }
  229.         for (partno = 0; partno < npart; ++partno) {
  230.             if ((partinfo[partno].p_flg & P_EXISTS) &&
  231.                 (partinfo[partno].p_siz != (SECTOR)0) &&
  232.                 (((partinfo[partno].p_id[0] == 'G') &&
  233.                  (partinfo[partno].p_id[1] == 'E') &&
  234.                  (partinfo[partno].p_id[2] == 'M'))   ||
  235.                  ((partinfo[partno].p_id[0] == 'B') &&
  236.                  (partinfo[partno].p_id[1] == 'G') &&
  237.                  (partinfo[partno].p_id[2] == 'M'))))   
  238.             {
  239.                 if (nlogdevs > EXTRALOGD)    {
  240.                     continue;
  241.                 }
  242.                 logmap[nlogdevs].lm_physdev = dev;
  243.                 logmap[nlogdevs].lm_partno = partno;
  244.                 logmap[nlogdevs].lm_start =  partinfo[partno].p_st;
  245.                 logmap[nlogdevs].lm_siz =      partinfo[partno].p_siz;
  246.                 ++nlogdevs;
  247.                 if (nlogdevs == MAXLOGDEVS)         {
  248.                     showmany = 1;
  249.                 }
  250.             }
  251.         }
  252.     }
  253.     inipart(partinfo, npart);
  254.     if (partinfo > 0)    Mfree(partinfo);
  255.     }
  256.  
  257.     if ((maxloop > 16) && (ttscsi))    {
  258.         maxloop = 16;
  259.         dev = 8;
  260.         goto rerescan;
  261.     } else if (((maxloop > 16) && (!ttscsi)) || ((ttscsi)&&(maxloop>8)))    {
  262.         maxloop = 8;
  263.         dev = 0;
  264.         goto rerescan;
  265.     }
  266.     erasemsg();
  267.     return OK;
  268. }
  269.  
  270. /* rerange the partition informations. */
  271.  
  272.  sortpart(pinfo, type)
  273.  PART *pinfo;
  274.  int type;                /* USER_ED = 1: for user interface use */
  275.                          /* SCAN_BS = 0: for rescan() and laybs() use */
  276.  {
  277.      int i, j, k;
  278.     PART rpart[2];
  279.  
  280.     if (ext == NO_EXT) return OK;    /* don't need sort */
  281.     for (i = 0; i < 2; i++)    { /* initialize the temple space */
  282.         rpart[i].p_flg = 0L;
  283.         rpart[i].p_st = 0L;
  284.         rpart[i].p_siz = 0L;
  285.         for (k = 0; k < 3; k++)
  286.             rpart[i].p_id[k] = '0';
  287.     }
  288.     /* save the partitions that after the extened partitions */
  289.     for (i = ext+1, j=0; i < 4; i++, j++)        {
  290.         if (pinfo[i].p_flg & P_EXISTS)    {
  291.             rpart[j].p_flg = P_EXISTS;
  292.             rpart[j].p_st = pinfo[i].p_st;
  293.             rpart[j].p_siz = pinfo[i].p_siz;
  294.             for (k = 0; k < 3; k++)
  295.                 rpart[j].p_id[k] = pinfo[i].p_id[k];
  296.         } 
  297.     }
  298.     /* move the extened partition to the front */
  299.      for (i=4, j = ext; i < npart; i++, j++)    {
  300.         if (pinfo[i].p_flg & P_EXISTS)    {
  301.             pinfo[j].p_flg = P_EXISTS;
  302.             pinfo[j].p_st = (type)?(pinfo[i].p_st):(pinfo[i].p_st + ROOTSECT);
  303.             pinfo[j].p_siz = (type)?(pinfo[i].p_siz):(pinfo[i].p_siz-ROOTSECT);
  304.             for (k = 0; k < 3; k++)
  305.                 pinfo[j].p_id[k] = pinfo[i].p_id[k];
  306.         } else { j--;}    /* stay with that space */
  307.     }
  308.     /* copy the not extended partitions back after the extended partitions */
  309.      for (i=0; i < 2; i++, j++)    {
  310.         if (rpart[i].p_flg & P_EXISTS)    {
  311.             pinfo[j].p_flg = P_EXISTS;
  312.             pinfo[j].p_st = rpart[i].p_st;
  313.             pinfo[j].p_siz = rpart[i].p_siz;
  314.             for (k = 0; k < 3; k++)
  315.                 pinfo[j].p_id[k] = rpart[i].p_id[k];
  316.         } else {j--;}
  317.     }
  318.     for (i = j; i < npart; i++)    { /* set the rest to 0 */
  319.         pinfo[i].p_flg = 0L;
  320.         pinfo[i].p_st = 0L;
  321.         pinfo[i].p_siz = 0L;
  322.         for (k = 0; k < 3; k++)
  323.             pinfo[i].p_id[k] = '0';
  324.     }
  325. }
  326.  
  327.  
  328. /* 
  329.  * check to find out the exist of device
  330.  */
  331.  
  332. rangelog(dev)
  333.  
  334. int dev;
  335.  
  336. {
  337.     PUNINFO *divinfo;
  338.     int devnum;
  339.  
  340.     ostack = Super(NULL);
  341.     divinfo = ((PUNINFO *) *((long *)(0x516)));
  342.     for (devnum = 0; devnum < MAXUNITS; ++devnum)    {
  343.         if ((int)(divinfo->pun[devnum] & 0x07) == dev)    {
  344.             delay();
  345.             nlogdevs++;
  346.         }
  347.     }
  348.     Super(ostack);
  349. }
  350.  
  351. /*
  352.  * From a PHYSICAL device unit (0->7)
  353.  * and a partition number (0->3), figure
  354.  * out the LOGICAL disk number ('C'->'P').
  355.  *
  356.  * return the LOGICAL disk number or
  357.  * ERROR if the PHYSICAL device doesn't exist.
  358.  *
  359.  */
  360. phys2log(pdev, pno)
  361. int  pdev;    /* physical device unit */
  362. int  pno;    /* partition number (0 -> 3) */
  363. {
  364.     int logdev;        /* index to step through partitions of a phys unit */
  365.  
  366.     for (logdev = 0; logdev < EXTRALOGD; logdev++) {
  367.         if (logmap[logdev].lm_physdev == pdev &&
  368.             logmap[logdev].lm_partno == pno)
  369.             return ('C'+logdev);
  370.     }
  371.     return ERROR;
  372. }
  373.  
  374.  
  375. /*
  376.  * Map block on logical device to
  377.  * block on physical device;
  378.  * return ERROR if the logical device
  379.  * doesn't exist.
  380.  */
  381. log2phys(adev, ablk)
  382. int *adev;
  383. SECTOR *ablk;
  384. {
  385.     int dev;
  386.     char xbuf[256];
  387.     
  388.     dev = *adev;
  389.     if (dev >= 0 && dev <= 17)
  390.     return OK;
  391.  
  392.     dev = toupper(dev);
  393.     if (dev >= 'C' && dev <= 
  394.                 ('C'+EXTRALOGD)) /* from C to 't' are 50 logic device */
  395.     {
  396.     dev -= 'C';
  397.     *adev = logmap[dev].lm_physdev;
  398.     *ablk = logmap[dev].lm_start + *ablk;
  399.     return OK;
  400.     }
  401.  
  402.     return ERROR;
  403. }
  404.  
  405.  
  406.  
  407. /*
  408.  * Return physical starting block# of a partition
  409.  *
  410.  */
  411. SECTOR 
  412. logstart(ldev)
  413. int ldev;    /* logical device */
  414. {
  415.     ldev = toupper(ldev);
  416.     if (ldev >= 'C' && ldev <= 
  417.                 ('C'+EXTRALOGD)){/*from C to 't' are 50 logic device */
  418.         ldev -= 'C';
  419.         return (logmap[ldev].lm_start);
  420.     }
  421.     return ERROR;
  422. }
  423.  
  424.  
  425.  
  426. /*
  427.  * Return physical starting block# of a partition's data block.
  428.  *
  429.  */
  430. SECTOR 
  431. logend(ldev)
  432. int ldev;    /* logical device */
  433. {
  434.     ldev = toupper(ldev);
  435.     if (ldev >= 'C' && ldev <= 
  436.                 ('C'+EXTRALOGD)){/*from C to 't' are 50 logic device */
  437.         ldev -= 'C';
  438.         return (logmap[ldev].lm_start+logmap[ldev].lm_siz-1);
  439.     }
  440.     return ERROR;
  441. }
  442.  
  443.  
  444. #define    MFM 17        /* sectors per track for MFM */
  445. #define    RLL 26        /* sectors per track for RLL */
  446.  
  447.  
  448. /*
  449.  * Check if dev's root block is intact.
  450.  * Return number of sectors per track on disk.
  451.  *
  452.  */
  453. chkroot(dev, bs)
  454. int dev;
  455. char *bs;
  456. {
  457.     extern long get3bytes();
  458.     extern long get4bytes();
  459.     SETMODE *mb;
  460.     int i, ret, set, scsidrv, mask=0x0001;
  461.     int cyl, head;
  462.     SECTOR size, msiz;    /* size of media */
  463.     char buf[512], sendata[32];
  464.     long dmaptr, tmpptr;
  465.     char *dmahigh=0xffff8609,
  466.          *dmamid=0xffff860b,
  467.          *dmalow=0xffff860d;
  468.     
  469.     size = ((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_siz;
  470.     ostack = Super(NULL);
  471.     
  472.     ret = OK;
  473.     if (dev == 16)    {        /* it is a IDE-AT drive */
  474.         msiz = (SECTOR)athead * (SECTOR)atcyl * (SECTOR)atspt;
  475.         if (size != msiz)
  476.             ret = ERROR;
  477.         delay();
  478.         Super(ostack);
  479.         return(ret);
  480.     } else if (dev > 7)    {    /* it is a scsi drive */
  481.         if ((ret = readcap(dev, 0, (long)0, sendata)) == OK) {
  482.             msiz = get4bytes(sendata) + 1;
  483.             if (size != msiz)
  484.                 ret = ERROR;
  485.             delay();
  486.             Super(ostack);
  487.             return(ret);
  488.         }
  489.         goto chkerr;
  490.     }
  491.  
  492.     /* Get format parameters/ disk size from media */
  493.     set = typedev & (mask << dev);
  494.     scsidrv = typedrv & (mask << dev);
  495.     for (i = 0; i < 32; i++)
  496.         sendata[i] = 0;
  497.     if ((set) || (scsidrv))    {
  498.         ret = mdsense(dev, 4, 0, 32, sendata);     /* use page code 4, but get */
  499.                                             /* info from the mdsense header */
  500.         if (!get3bytes(sendata+5))    {        /* no hsize retured */
  501.             delay();
  502.             ret = mdsense(dev, 0, 0, 16, sendata);/* use page code 4, but get */
  503.             if (!get3bytes(sendata+5))    {        /* no hsize retured */
  504.                 err(needinfo);
  505.                 delay();
  506.                 Super(ostack);
  507.                 return(-3);
  508.             }
  509.         }
  510.     } else    {
  511.         ret = mdsense(dev, 0, 0, 22, sendata);
  512.     }
  513.  
  514. chkerr:
  515.     delay();
  516.     Super(ostack);
  517.     
  518.     if (ret != 0) {
  519.         ret = errcode(dev);
  520.         if (tsterr(ret) != OK) 
  521.             return ERROR;
  522.         return (-3);    /* don't have to show the alert box */
  523.     }
  524.     
  525.     /* check what kind of sense data it returned  */
  526.     /* If full SCSI, will return number of blocks */
  527.     /* on disk at byte 5, 6 and 7.  If Adaptec,   */
  528.     /* will return 0 for number of blocks on disk */
  529.     /* on SCSI. */
  530.     
  531.     if (!(msiz = get3bytes(sendata+5))) {    /* no disk size returned? */
  532.         /* Yup, ie., it's adaptec's.  Interpret as SETMODE structure */
  533.         mb = (SETMODE *)sendata;
  534.     /* get number of cylinders */
  535.     cyl = mb->smd_cc[0];
  536.     cyl <<= 8;
  537.     cyl |= mb->smd_cc[1];
  538.     
  539.     /* get number of heads */
  540.     head = mb->smd_dhc;
  541.     
  542.     msiz = (SECTOR)head * (SECTOR)cyl * MFM;
  543.     
  544.     for (i = 0; i < 20; i++) {
  545.         if ((ret = rdsects(dev, 1, buf, msiz+i)) == OK) {
  546.         
  547.         /* find out whether data has been transferred, by
  548.               checking if dma pointer has been moved.      */
  549.  
  550.            ostack = Super(NULL);    /* get into Supervisor mode */
  551.            
  552.         dmaptr = *dmahigh;
  553.         dmaptr &= 0x0000003f;
  554.         dmaptr <<= 16;
  555.         tmpptr = *dmamid;
  556.         tmpptr &= 0x000000ff;
  557.         tmpptr <<= 8;
  558.         dmaptr |= tmpptr;
  559.         tmpptr = *dmalow;
  560.         tmpptr &= 0x000000ff;
  561.         dmaptr |= tmpptr;
  562.         
  563.             delay();
  564.             Super(ostack);        /* back to user mode */
  565.             
  566.         if (dmaptr != buf)
  567.             break;
  568.         } else {            /* rdsects return an error */
  569.         if (tsterr(ret) == OK) {
  570.                 break;
  571.         }
  572.             }
  573.         }
  574.     
  575.     if (ret == MDMCHGD)        /* check if error occurred */
  576.         return (ret);
  577.        
  578.     /* Determine if media is MFM or RLL */
  579.     if (i < 20)
  580.         msiz = (SECTOR)head * (SECTOR)cyl * RLL;
  581.     }
  582.  
  583.         
  584.     if (size != msiz)
  585.         ret = ERROR;
  586.     else 
  587.         ret = OK;
  588.         
  589.     return (ret);
  590. }
  591.  
  592.  
  593. /*
  594.  * Chkparm()
  595.  *    Check if given logical device has the asssumed parameters.
  596.  * Assumptions are:
  597.  *    - 512 bytes/sector
  598.  *    - 2 sectors/cluster
  599.  *    - 1 reserved sector
  600.  *    - 2 FATs
  601.  *
  602.  * Input:
  603.  *    ldev - logical device number ('C' -> 'P').
  604.  *
  605.  * Return:
  606.  *    OK - parameters of partition match the assumptions
  607.  *    ERROR - something went wrong.
  608.  *
  609.  * Comment:
  610.  *    Number of FATs is assumed to be 2.  Cannot check this 
  611.  * because previous version of HDX did not put that in the boot
  612.  * sector.
  613.  */
  614. chkparm(ldev)
  615. int ldev;
  616. {
  617.     char bs[512];        /* boot sector */
  618.     BOOT *boot;            /* boot structure */
  619.     UWORD bps, res, siz;    /* bytes/sector, num reserved sectors, ldev size */
  620.     int ret;
  621.  
  622.     if ((ret = rdsects(ldev, 1, bs, (SECTOR)0)) != 0) {
  623.         if (tsterr(ret) != OK)
  624.             err(bootread);
  625.         ret = ERROR;
  626.         goto parmend;
  627.     }    
  628.  
  629.     boot = (BOOT *)bs;
  630.     gw((UWORD *)&boot->b_bps, &bps);    /* what is number bytes/sector? */
  631.     gw((UWORD *)&boot->b_res, &res);    /* what is num of reserved sectors? */
  632.     gw((UWORD *)&boot->b_nsects, &siz);    /* what is size of partition */
  633.     if (bps % BPS            /* bytes per sector == ratio of 512 ? */
  634.     || res != 1) {            /* num sectors reserved == 1 ? */
  635.     ret = ERROR;            /* Nope, different from assumptions */
  636.     goto parmend;
  637.     }
  638.     
  639.     /* Check if sectors per cluster make sense */
  640.     if (boot->b_spc != 2) {
  641.         ret = ERROR;
  642.         goto parmend;
  643.     }
  644.     
  645.     ret = OK;                /* If yes, return OK */
  646.  
  647. parmend:
  648.     return ret;
  649. }
  650.  
  651.  
  652. ichkparm(ldev)
  653. int ldev;
  654. {
  655.     char bs[512];        /* boot sector */
  656.     BOOT *boot;            /* boot structure */
  657.     UWORD bps, res, siz;    /* bytes/sector, num reserved sectors, ldev size */
  658.     int ret;
  659.  
  660.     if ((ret = rdsects(ldev, 1, bs, (SECTOR)0)) != 0) {
  661.         if (tsterr(ret) != OK)
  662.             err(bootread);
  663.         ret = ERROR;
  664.         goto parmend;
  665.     }    
  666.  
  667.     boot = (BOOT *)bs;
  668.     gw((UWORD *)&boot->b_bps, &bps);    /* what is number bytes/sector? */
  669.     gw((UWORD *)&boot->b_res, &res);    /* what is num of reserved sectors? */
  670.     gw((UWORD *)&boot->b_nsects, &siz);    /* what is size of partition */
  671.     if (bps != 512            /* bytes per sector == 512 ? */
  672.     || res != 1) {            /* num sectors reserved == 1 ? */
  673.     ret = ERROR;            /* Nope, different from assumptions */
  674.     goto parmend;
  675.     }
  676.     
  677.     /* Check if sectors per cluster make sense */
  678.     if ((siz >= 0x8000L && boot->b_spc != 4) ||
  679.         (siz < 0x8000L && boot->b_spc != 2)) {
  680.         ret = ERROR;
  681.         goto parmend;
  682.     }
  683.     
  684.     ret = OK;                /* If yes, return OK */
  685.  
  686. parmend:
  687.     return ret;
  688. }
  689.  
  690.  
  691. /*
  692.  * Get dev's root block.
  693.  *
  694.  */
  695. getroot(dev, buf, sect)
  696. int dev;
  697. char *buf;
  698. SECTOR sect;
  699. {
  700.     return rdsects(dev, 1, buf, sect);
  701. }
  702.  
  703.  
  704. /*
  705.  * Put dev's root block.
  706.  *
  707.  */
  708. putroot(dev, buf, sect)
  709. int dev;
  710. char *buf;
  711. SECTOR sect;
  712. {
  713.     return wrsects(dev, 1, buf, sect);
  714. }
  715.  
  716.  
  717. /*
  718.  *  Read sector(s) from dev.
  719.  *
  720.  *  Input:
  721.  *    dev - device number (logical or physical).
  722.  *    num - number of sectors to read.
  723.  *    buf - buffer to write data read.
  724.  *    sect - starting sector number to read from.
  725.  *
  726.  *  Return:
  727.  *    errnum - 0: if read is successful.
  728.  *         an error code: if read is unsuccessful.
  729.  */
  730. rdsects(dev, num, buf, sect)
  731. int dev;            /* device number (logical or physical) */
  732. UWORD num;            /* number of sectors to read */
  733. char *buf;
  734. SECTOR sect;            /* starting sector to read from */
  735. {
  736.     int errnum;
  737.  
  738.     if (log2phys(&dev, §) < 0)
  739.     return ERROR;
  740.  
  741.     ostack = Super(NULL);
  742.     if (dev == 16)    { /* it is a AT drive */
  743.         errnum = ideread(athead, atspt, sect, num, buf, (UWORD)dev);
  744.     } else {
  745.         errnum = hread(sect, num, buf, (UWORD)dev);
  746.     }
  747.     /*
  748.     if (errnum == 04)    {      the drive is stop 
  749.         delay();
  750.         stunt();
  751.         delay();
  752.         errnum = hread(sect, num, buf, (UWORD)dev);
  753.     }
  754.     */
  755.     delay();
  756.     Super(ostack);
  757.  
  758.     if (errnum > 0) {
  759.         errnum = errcode(dev);
  760.     }
  761.         
  762.     return errnum;        /* return the error code */
  763. }
  764.  
  765.  
  766. /*
  767.  *  Write sector(s) to dev.
  768.  *
  769.  *  Input:
  770.  *    dev - device number (logical or physical).
  771.  *    num - number of sectors to write.
  772.  *    buf - buffer with data to be written.
  773.  *    sect - starting sector number to write to.
  774.  *
  775.  *  Return:
  776.  *    errnum - 0: if write is successful.
  777.  *         an error code: if write is unsuccessful.
  778.  */
  779. wrsects(dev, num, buf, sect)
  780. int dev;            /* device number (logical or physical */
  781. UWORD num;            /* number of sectors to write */
  782. char *buf;            /* buffer with data to be written */
  783. SECTOR sect;            /* starting sector to write to */
  784. {
  785.     int errnum;
  786.  
  787.     if (log2phys(&dev, §) < 0)
  788.     return ERROR;
  789.  
  790.     ostack = Super(NULL);
  791.     if (dev == 16)    { /* it is a AT drive */
  792.         errnum = idewrite(athead, atspt, sect, num, buf, (UWORD)dev);
  793.     } else {
  794.         errnum = hwrite(sect, num, buf, (UWORD)dev);
  795.     }
  796.     delay();
  797.     Super(ostack);
  798.  
  799.     if (errnum > 0) {
  800.         errnum = errcode(dev);
  801.     }
  802.  
  803.     return errnum;
  804. }
  805.  
  806.  
  807. /*
  808.  * Zero range of sectors on dev.
  809.  *
  810.  */
  811. zerosect(dev, start, count)
  812. int dev;
  813. SECTOR start;
  814. UWORD count;
  815. {
  816.     char *zbuf;
  817.     int  v;
  818.     UWORD i;
  819.  
  820.     if ((zbuf = (char *)mymalloc(ZBUFSIZ)) <= 0)
  821.         return err(nomemory);
  822.         
  823.     if (log2phys(&dev, &start) < 0) {
  824.         free(zbuf);
  825.     return ERROR;
  826.     }
  827.  
  828.     fillbuf(zbuf, (long)ZBUFSIZ, 0L);
  829.  
  830.     while (count)
  831.     {
  832.         if (count > ZCOUNT)
  833.             i = ZCOUNT;
  834.         else i = count;
  835.  
  836.     if ((v = wrsects(dev, i, zbuf, start)) != 0)
  837.         break;
  838.     start += i;
  839.     count -= i;
  840.     }
  841.     free(zbuf);
  842.     
  843.     return v;
  844. }
  845.